package com.cvte.sunkit.manage

import android.annotation.SuppressLint
import android.content.res.Resources
import android.graphics.*
import android.hardware.display.DisplayManager
import android.media.Image
import android.media.ImageReader
import android.os.Environment
import android.util.DisplayMetrics
import android.util.Log
import com.cvte.sunkit.App
import com.cvte.sunkit.callback.RecordAbnormalListener
import com.cvte.sunkit.model.AbnormalPerfData
import com.cvte.sunkit.model.PerfData
import com.cvte.sunkit.tools.FpsTool
import com.cvte.sunkit.utils.ImageSaveUtil
import kotlinx.coroutines.delay
import java.io.*
import java.text.SimpleDateFormat
import java.util.*
import kotlin.properties.Delegates


/**
 *  @PackageName com.cvte.sunkit.manage
 *  @Description 用户未开启异常数据记录时，应用主动对异常数据做记录
 *  @Author lixu
 *  @Data 2023/7/25 10:06
 *  @Version 1.0
 */
open class AbnormalDataRecordManager : RecordAbnormalListener {
    private lateinit var mAbnormalPrefData: AbnormalPerfData//异常数据

    private var mAbnormalDataList = mutableListOf<AbnormalPerfData>()

    private var mWidth by Delegates.notNull<Int>()
    private var mHeight by Delegates.notNull<Int>()


    companion object {
        private const val FILE_NAME = "异常数据"
        private const val TAG = "AbnormalDataRecordManage"
    }

    override fun startRecordAbnormalData() {
        writeDataRecord()
    }

    fun setData(
        perfData: PerfData,
        memAvailThreshold: Long,
        sysCpuUsageThreshold: Double,
        inSpeedThreshold: Double,
        outSpeedThreshold: Double,
    ) {
        mAbnormalPrefData = AbnormalPerfData(
            memAvailThreshold, sysCpuUsageThreshold,
            inSpeedThreshold, outSpeedThreshold, FpsTool.FpsDataWrapper(60, 10, 20, 18.0), perfData
        )
        mAbnormalDataList.add(mAbnormalPrefData) // 暂时无法采集到准确的帧率数据，写成固定值阈值过滤
        if (mAbnormalDataList.size > 10) {
            writeDataRecord()
        }
    }

    override fun stopRecordAbnormalData() {
        writeDataRecord()
        mAbnormalDataList.clear()
    }

    @SuppressLint("SimpleDateFormat")
    private fun shiftTimeFormat(currentTime: Long): String {
        val date = Date(currentTime)
        val pattern = "MM/dd_HH:mm:ss"
        val sdf = SimpleDateFormat(pattern)
        val formattedDateTime = sdf.format(date)
        return formattedDateTime.toString()
    }

    private fun loadSaveDir(child:String): File? {
        val baseFile = File(Environment.getExternalStorageDirectory(), child) // 加载数据保存目录
        Log.i(RecordManager.TAG, "loadSaveDir: ${baseFile.absoluteFile}")
        if (!baseFile.exists()) {
            val result = baseFile.mkdirs()
            if (!result) {
                return null
            }
        }
        return baseFile
    }

    private fun writeDataRecord() {
        val file: File? = loadSaveDir("sunkit")
        val charsetName = "GBK"
        val saveFile = File(file, "${FILE_NAME}.csv")
        if (file?.canWrite() == true) {
            if (saveFile.createNewFile()) run {
                val writer =
                    BufferedWriter(OutputStreamWriter(FileOutputStream(saveFile), charsetName))
                writer.write("系统时间,发生时间(s),空闲内存(mb),此时阈值(mb),cpu占用(%),此时阈值(%),当前帧率,延迟数,最长延时(ms),延迟占比(%),读取速率(mb/s),此时阈值(mb/s),写回速率(mb/s),此时阈值(mb/s)\n")
                writer.flush()
                writer.close()
            } else {
                val writer =
                    BufferedWriter(
                        OutputStreamWriter(
                            FileOutputStream(saveFile, true),
                            charsetName
                        )
                    )

                for (data in mAbnormalDataList) { // 追加写入新的数据
                    writer.append(
                        "${data.perfData.currentTime},${(shiftTimeFormat(data.perfData.currentTime))},${data.perfData.memAvail},${data.memAvailThreshold},${data.perfData.sysCpuUsage},${data.sysCpuUsageThreshold}," +
                                "${data.perfData.fpsDataWrapper.fps},${data.perfData.fpsDataWrapper.junkCount},${data.perfData.fpsDataWrapper.maxJunk}," +
                                "${data.perfData.fpsDataWrapper.junkPercent},${data.perfData.inSpeed},${data.inSpeedThreshold},${data.perfData.outSpeed},${data.outSpeedThreshold}\n"
                    )
                    writer.flush()
                }
                writer.close()
            }
            mAbnormalDataList.clear()
            App.canReadAndWriteFile = true
        } else {
            App.canReadAndWriteFile = false // 文件不可读或写，用于读写权限不足提示用户的标识字段
            Log.i(TAG, "writeDataRecord: $saveFile 文件路径不可写")
        }
    }

    // 获取屏幕截图
    @SuppressLint("WrongConstant")
    suspend fun captureScreen(resource: Resources) {
        val metrics: DisplayMetrics = resource.displayMetrics
        mWidth= metrics.widthPixels
        mHeight = metrics.heightPixels
        val imageReader = ImageReader.newInstance(mWidth, mHeight, PixelFormat.RGBA_8888, 1)

        App.mediaProjection!!.createVirtualDisplay(
            "ScreenCapture", mWidth, mHeight, metrics.densityDpi,
            DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
            imageReader.surface, null, null
        )
        // 获取截图的最新图像
        delay(1000) // 为什么要延时呢，防止imageReader.acquireLatestImage()还没获取到图片，导致image始终为null
        val image = imageReader.acquireLatestImage()
        if (image != null) {
            saveJpeg(image, name = (System.currentTimeMillis().toString()) )
            image.close() // 释放资源
            App.mediaProjection!!.stop()
        }
    }
    private fun saveJpeg(image: Image, name: String) {
        val planes = image.planes
        val buffer = planes[0].buffer
        val pixelStride = planes[0].pixelStride
        val rowStride = planes[0].rowStride
        val rowPadding: Int = rowStride - pixelStride * mWidth
        val bitmap =
            Bitmap.createBitmap(mWidth + rowPadding / pixelStride, mHeight, Bitmap.Config.ARGB_8888)
        bitmap.copyPixelsFromBuffer(buffer)
        loadSaveDir("sunkitPicture")?.let {
            ImageSaveUtil.saveBitmap2file(bitmap, App.mInstance.applicationContext, name,
                it
            )
        }
    }

}